package com.kj.tms.system.service.menu.serviceImpl;

import com.kj.tms.common.bean.dto.ReturnData;
import com.kj.tms.common.bean.dto.TreeCheck;
import com.kj.tms.common.bean.dto.TreeData;
import com.kj.tms.common.bean.dto.TreeNode;
import com.kj.tms.common.bean.exception.BusinessException;
import com.kj.tms.common.bean.redis.RedisAccess;
import com.kj.tms.common.bean.session.SessionManager;
import com.kj.tms.common.utils.JsonUtils;
import com.kj.tms.common.utils.StringUtil;
import com.kj.tms.common.utils.constant.Consts;
import com.kj.tms.common.utils.uuid.IdGen;
import com.kj.tms.pri.system.menu.dto.ModuleDto;
import com.kj.tms.pri.system.menu.service.ModuleService;
import com.kj.tms.pri.system.user.dto.UserDto;
import com.kj.tms.system.service.menu.dao.ModuleMapper;
import net.sf.json.JSONArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

import java.util.*;


/**
 * <p>项目名称：system<p>
 * <p>类名称：ModuleServiceImpl<p>
 * <p>类描述：字典表业务实现类<p>
 *
 * @author 创建人：yangruidong
 * @author 创建时间： 2017年10月26日 9:41
 * @author 修改人：yangruidong
 * @author 修改时间：2017年10月26日 9:41
 * @author 修改备注：
 * @version: 2017年10月18日
 */
@Service
@Transactional
public class ModuleServiceImpl implements ModuleService {
    public final static Logger logger = LoggerFactory.getLogger(ModuleServiceImpl.class);
    @Autowired
    private ModuleMapper moduleMapper;
    @Autowired
    private RedisAccess redisAccessImpl;
    @Autowired
    private SessionManager sessionManager;
    public ModuleMapper getMapper() {
        return moduleMapper;
    }

    @Override
    public ReturnData queryByList(@RequestBody(required = false) ModuleDto moduleDto) {
        List<ModuleDto> dataList = moduleMapper.listByCondition(moduleDto);
        //设置页面数据
        Map<String, Object> returnObject = new HashMap<String, Object>();

        returnObject.put("rows", dataList);
        returnObject.put("total", dataList.size());
        if (dataList.size() > 0) {
            return new ReturnData(Consts.SUCCESS, "", returnObject);
        }
        return new ReturnData(Consts.ERROR, "没有数据", returnObject);
    }

    /**
     * @param map
     * @return ModuleDto
     * @throws
     * @method [getModuleDto]
     * @description [获取单个module]
     * @author 王国庆
     * @version 1.0
     * @date 2017年11月09日 16:08
     */
    @Override
    public ModuleDto getModuleDto(@RequestBody(required = false) Map map) {
        return moduleMapper.getModuleDto(map);
    }

    /**
     * @param moduleDto
     * @return ReturnData
     * @throws
     * @method [checkModuleName]
     * @description [校验模块名称]
     * @author 王国庆
     * @version 1.0
     * @date 2017年11月16日 16:08
     */
    @Override
    public ReturnData checkModuleName(@RequestBody(required = false) ModuleDto moduleDto) {

        Map paraMap = new HashMap();
        paraMap.put("parentMenuCode", moduleDto.getParentMenuCode());
        paraMap.put("menuName", moduleDto.getMenuName());

        ModuleDto paraDto = getModuleDto(paraMap);
        if (paraDto != null) {
            return new ReturnData(Consts.SUCCESS, "校验模块名称成功");
        }
        return new ReturnData(Consts.ERROR, "校验模块名称失败");
    }

    /**
     * 插入
     *
     * @param moduleDto
     */

    public ReturnData save(@RequestBody(required = false) ModuleDto moduleDto) {
        try {
            //menuId为空为插入操作 ，部位空为update操作
            if (moduleDto.getMenuId() == null) {
                moduleDto.setMenuId(IdGen.getId());
                moduleDto.setAuthMark("");
                //插入
                moduleMapper.save(moduleDto);
                updateRedisData(moduleDto, "save");
                return new ReturnData(Consts.SUCCESS, "保存成功");

            } else {
                /*判断是否有子节点*/
                if (this.isParent(moduleDto)) {
                    Map paraMap = new HashMap();
                    paraMap.put("menuId", moduleDto.getMenuId());
                    //获取数据库中得 menuCode
                    ModuleDto paramModule = getModuleDto(paraMap);
                    //判断父节点是否被修改
                    if (!(paramModule.getMenuCode().equals(moduleDto.getMenuCode()))) {
                        return new ReturnData("0", "子节点非空，不可修改代码~");
                    }
                }
                this.update(moduleDto);
                updateRedisData(moduleDto, "update");
                return new ReturnData(Consts.SUCCESS, "更新成功");

            }
        } catch (Exception e) {
            throw new BusinessException(Consts.ERROR, "保存失败", e);
        }
    }

    /**
     * 更新
     *
     * @param moduleDto
     */
    public void update(@RequestBody(required = false) ModuleDto moduleDto) {
        moduleMapper.update(moduleDto);
    }

    /**
     * 删除
     *
     * @param moduleDto
     */
    public ReturnData delete(@RequestBody(required = false) ModuleDto moduleDto) {
        try {
            moduleMapper.delete(moduleDto);
            deleteRedisData(moduleDto.getMenuId());
        } catch (Exception e) {
            return new ReturnData(Consts.ERROR, "删除失败"+e.getMessage(), e);
        }
        return new ReturnData(Consts.SUCCESS, "删除成功", null);
    }

    @Override
    public void saveOrUpdate(@RequestBody(required = false) ModuleDto moduleDto) {
        moduleMapper.saveOrUpdate(moduleDto);
    }

    /**
     * 获取主键
     *
     * @param tableName
     * @return
     */
    @Override
    public String getSequence(@RequestParam("tableName") String tableName) {

        String sequence = "SEQ_" + tableName;

        String str = moduleMapper.getSequence(sequence) + "";

        return str;

    }

    /**
     * 判断是否为父节点
     *
     * @param moduleDto
     * @return
     */
    @Override
    public boolean isParent(@RequestBody(required = false) ModuleDto moduleDto) {

        ModuleDto paramModule = new ModuleDto();

        paramModule.setParentMenuCode(moduleDto.getOriginalCode());

        List<ModuleDto> moduleDtoList = moduleMapper.listByCondition(paramModule);

        if (moduleDtoList.size() > 0) {
            return true;
        }
        return false;
    }

    /**
     * 获取上级模块的有效标识
     *
     * @param moduleDto
     * @return
     */
    @Override
    public String getParentValid(@RequestBody(required = false) ModuleDto moduleDto) {

        Map paraMap = new HashMap<>();
        //如果父节点为空 直接启用
        if ("".equals(moduleDto.getParentMenuCode())) {
            return "";
        }

        paraMap.put("menuCode", moduleDto.getParentMenuCode());

        ModuleDto paramModule = getModuleDto(paraMap);

        return paramModule.getValidMark();
    }

    /**
     * 递归设置某节点及其所有子节点的有效标识
     *
     * @param dto
     * @param status
     */
    public void setAllValid(@RequestBody(required = false)ModuleDto dto, @RequestParam("status") String status) {
        //如果是父节点递归禁止子节点，否则直接禁止
        if (isParent(dto)) {
            Map paraMap = new HashMap<>();

            paraMap.put("parentMenuCode", dto.getMenuCode());
            //获取子节点
            List<ModuleDto> dataList = moduleMapper.listForValid(paraMap);

            for (ModuleDto dto1 : dataList) {
                setAllValid(dto1, status);
                dto.setValidMark(status);
                moduleMapper.update(dto);
                updateRedisData(dto,"update");
            }
        }
        dto.setValidMark(status);
        moduleMapper.update(dto);
        updateRedisData(dto,"update");
    }


    @Override
    public List<ModuleDto> queryMenuByUserOrg(@RequestBody(required = false) Map map) {
        return moduleMapper.queryMenuByUserOrg(map);
    }

    /**
     * @param @return 设定文件
     * @return JSONArray    返回类型
     * @throws
     * @Title: getMenu
     * @Description: 获取用户菜单
     */
    public JSONArray getMenu( @RequestBody(required = false) List<ModuleDto> ModuleDtoList) {

        JSONArray curUserJsonMenus = new JSONArray();

        if (ModuleDtoList.size() > 0) {
            List<TreeNode> treeNodes = new ArrayList<TreeNode>();
            for (int i = 0; i < ModuleDtoList.size(); i++) {
                ModuleDto moduleDto = ModuleDtoList.get(i);
                TreeCheck treeNode = new TreeCheck();
                treeNode.setId(moduleDto.getMenuCode());
                treeNode.setpId(moduleDto.getParentMenuCode());
                treeNode.setName(moduleDto.getMenuName());
                treeNode.setJc(moduleDto.getMenuCode().length() / 2);
                treeNode.setXh(Integer.parseInt(moduleDto.getMenuNum()));
                treeNode.setAction_url(moduleDto.getMenuUrl());
                treeNode.setMenu_type(moduleDto.getMenuType());
                treeNodes.add(treeNode);
            }
            Collections.sort(treeNodes);
            curUserJsonMenus = JSONArray.fromObject(treeNodes);
            return curUserJsonMenus;
        }
        return curUserJsonMenus;
    }

    /**
     * @param @return 设定文件
     * @return JSONArray    返回类型
     * @throws
     * @Title: getSubMenu
     * @Description: 获取下级用户菜单
     */
    public Map<String, Object> getSubMenu(@RequestBody(required = false) ModuleDto model) {
        List<ModuleDto> dataList = new ArrayList<>();
        UserDto user = (UserDto) sessionManager.getAttribute(Consts.USER);
        List<ModuleDto> moduleDtoList = user.getModuleDtos();
        Map<String, Object> returnObject = new HashMap<String, Object>();
        for (ModuleDto dto : moduleDtoList) {
            if ((StringUtil.isNull(model.getParentMenuCode()) && StringUtil.isNull(dto.getParentMenuCode())) ||
                    (StringUtil.isNotNull(dto.getParentMenuCode()) && dto.getParentMenuCode().equals(model.getParentMenuCode()))) {
                dataList.add(dto);
            }
            if (dto.getMenuCode().equals(model.getParentMenuCode())) {
                returnObject.put("dto", dto);
            }
        }
        Map<String, Object> map = new HashMap<>();
        map.put("parentMenuCode", model.getParentMenuCode());
        //设置页面数据
        returnObject.put("rows", dataList);
        return returnObject;
    }

    @Override
    public List<ModuleDto> queryMenuByRoleId(@RequestParam("Id") String Id) {
        return moduleMapper.queryMenuByRoleId(Id);
    }

    /**
     * 获取模块树加载数据
     *
     * @return
     * @see [类、类#方法、类#成员]
     */
    @Override
    public List<TreeData> getTreeData(@RequestParam("roleId") String roleId) {
        try {
            //获取所有的菜单模块
            ModuleDto model = new ModuleDto();
            model.setValidMark(Consts.VALID_MARK_1);
            List<ModuleDto> datalist = moduleMapper.listByCondition(model);

            // 获取角色已分配的角色模块
            List<ModuleDto> datalist_assigned = moduleMapper.queryMenuByRoleId(roleId);

            //返回的结果集
            List<TreeData> results = new ArrayList<TreeData>();

            //根节点
            TreeData td = new TreeData();
            td.setName("系统功能菜单树");
            td.setpId("-1");
            td.setCode("0");
            td.setAction_url("0");
            td.setId("0");
            td.setTitle(td.getName());

            if (datalist_assigned.size() > 0) {
                td.setChecked(true);
            }

            results.add(td);

            //设置已分配模块的状态
            for (ModuleDto dto : datalist) {
                td = dtoToTreeData(dto);
                for (ModuleDto dto_assigned : datalist_assigned) {
                    if (dto.getMenuId().equals(dto_assigned.getMenuId())) {
                        td.setChecked(true);
                    }
                }
                results.add(td);
            }

            return results;
        } catch (Exception e) {
            throw new BusinessException(Consts.ERROR, "生成菜单模块树出现异常", e);
        }
    }

    /**
     * Dto转换到TreeData
     *
     * @param t
     * @return
     * @see [类、类#方法、类#成员]
     */
    public TreeData dtoToTreeData(@RequestBody ModuleDto t) {
        TreeData td = new TreeData();
        td.setAction_url(String.valueOf(t.getMenuUrl()));
        td.setCode(t.getMenuCode());
        //td.setName("["+ t.getCode() + "]-" + t.getName());
        td.setName(t.getMenuName());
        td.setId(t.getMenuCode());
        if (StringUtil.isNull(t.getParentMenuCode())) {
            td.setpId("0");
        } else {
            td.setpId(t.getParentMenuCode());
        }
        String type = "[%s]";
        if (t.getMenuType().equals("1")) {
            type = String.format(type, "导航");
        }
        if (t.getMenuType().equals("2")) {
            type = String.format(type, "页签");
        }
        if (t.getMenuType().equals("3")) {
            type = String.format(type, "按钮");
        }
        if (t.getMenuType().equals("4")) {
            type = String.format(type, "标题");
        }
        td.setTitle("[" + t.getMenuCode() + "]-" + td.getName() + "-" + type);
        return td;
    }

    /**
     * @see ModuleService#listByConditionMap(Map)
     */
    @Override
    public List<ModuleDto> listByConditionMap(@RequestBody(required = false) Map map) {

        return moduleMapper.listByConditionMap(map);
    }


    @Override
    public ReturnData updateValidMark(@RequestBody(required = false) ModuleDto moduleDto) {
        String status = moduleDto.getValidMark().equals(Consts.VALID_MARK_1) ? Consts.VALID_MARK_0 : Consts.VALID_MARK_1;

        moduleDto.setParentMenuCode("null".equals(moduleDto.getParentMenuCode()) ? "" : moduleDto.getParentMenuCode());

        if (status.equals(Consts.VALID_MARK_1) && !(getParentValid(moduleDto) == null)
                && getParentValid(moduleDto).equals(Consts.VALID_MARK_0)) {
            return new ReturnData(Consts.VALID_MARK_0, "不可启用", null);
        }
        try {
            //直接启用
            if (status.equals(Consts.VALID_MARK_1)) {
                moduleDto.setValidMark(status);
                update(moduleDto);
                updateRedisData(moduleDto,"update");
            } else {
                //递归禁止
                setAllValid(moduleDto, status);
            }
        } catch (Exception e) {
            logger.error(e.getMessage());
            return new ReturnData(Consts.ERROR, "保存失败");
        }
        return new ReturnData(Consts.SUCCESS, "操作成功", null);
    }

    /**
     * @return void
     * @method [updateRedisData]
     * @description [菜单模块 保存、修改或者禁用启用之后，更新redis]
     * @author 王国庆
     * @version 1.0
     * @date 2017年11月09日 10:04
     */
    private void updateRedisData(ModuleDto moduleDto, String type) {
        List<ModuleDto> moduleList = redisAccessImpl.lrandge(Consts.MODULE, 0, -1);
        if (!StringUtil.isEmptyOrNull(moduleList)) { //不考虑开始初始化没有值得情况
            logger.info("保存、修改或者禁用启用之后，更新redis 放 入角色列表------role size: " + moduleList.size());

            if ("save".equals(type)) {
                redisAccessImpl.lpush(Consts.ROLE, -1, moduleDto);
            } else {
                for (int k = 0; k < moduleList.size(); k++) {
                    ModuleDto dto = JsonUtils.Object2Bean(moduleList.get(k),ModuleDto.class);
                    //如果含有子节点，需要查询出来更改信息
                    if (moduleDto.getMenuId().equals(dto.getMenuId())) {
                        moduleDto = moduleMapper.getModuleDtoById(moduleDto.getMenuId());
                        redisAccessImpl.lset(Consts.ROLE, k, moduleDto);
                        break;
                    }
                }
            }
        }
    }

    /**
     * @return void
     * @method [deleteRedisData]
     * @description [菜单模块删除之后，更新redis]
     * @author 王国庆
     * @version 1.0
     * @date 2017年11月09日 10:04
     */
    private void deleteRedisData(String menuId) {
        List<ModuleDto> moduleList = redisAccessImpl.lrandge(Consts.MODULE, 0, -1);
        if (!StringUtil.isEmptyOrNull(moduleList)) {  //不考虑开始初始化没有值得情况
            for (int k = 0; k < moduleList.size(); k++) {
                ModuleDto dto = JsonUtils.Object2Bean(moduleList.get(k),ModuleDto.class);
                if (menuId.equals(dto.getMenuId())) {
                    redisAccessImpl.lremove(Consts.MODULE, k, moduleList.get(k));
                    break;
                }
            }
        }
    }

}
